﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Profile;
using System.Configuration;
using System.Data.SqlClient;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Web.Security;

namespace MP.Core.Authentication
{
    public class MPProfileProvider : System.Web.Profile.ProfileProvider
    {
        #region "Class Variables"

        private string connectionString;
        private string applicationName;

        #endregion

        #region "Properties"
        public override string ApplicationName
        {
            get
            {
                return applicationName;
            }
            set
            {
                applicationName = value;
            }
        }
        #endregion

        #region "Override"
        /// <summary>
        /// Initialize the provider.
        /// </summary>
        /// <param name="name">Name of the provider.</param>
        /// <param name="config">Configuration settings.</param>
        /// <remarks></remarks>
        public override void Initialize(
         string name,
         System.Collections.Specialized.NameValueCollection config
        )
        {

            // Initialize values from web.config.
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            if ((name == null) || (name.Length == 0))
            {
                name = "MPProfileProvider";
            }

            if (String.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "How Do I Profile provider");
            }

            // Initialize the abstract base class.
            base.Initialize(name, config);

            if ((config["applicationName"] == null) || String.IsNullOrEmpty(config["applicationName"]))
            {
                applicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
            }
            else
            {
                applicationName = config["applicationName"];
            }

            // Initialize connection string.
            ConnectionStringSettings connectionStringSettings =
              ConfigurationManager.ConnectionStrings[config["connectionStringName"]];

            if ((connectionStringSettings == null) || String.IsNullOrEmpty(connectionStringSettings.ConnectionString))
            {

                throw new Exception("Connection String cannot be blank.");
            }
            connectionString = connectionStringSettings.ConnectionString;

        }

        public override int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
        {
            SqlConnection sqlConnection = new SqlConnection(connectionString);
            SqlCommand sqlCommand = new SqlCommand("Profiles_Inactive_Del", sqlConnection);
            sqlCommand.CommandType = CommandType.StoredProcedure;
            sqlCommand.Connection = sqlConnection;
            SqlTransaction transaction = null;

            sqlCommand.Parameters.Add("deleted", SqlDbType.Int, 0);
            sqlCommand.Parameters["deleted"].Direction = ParameterDirection.Output;
            sqlCommand.Parameters.Add("inactivityDate", SqlDbType.DateTime, 0);
            if (authenticationOption == ProfileAuthenticationOption.Anonymous)
            {
                sqlCommand.Parameters.Add("isAnonymous", SqlDbType.Bit, 0).Value = 1;
            }
            else
            {
                sqlCommand.Parameters.Add("isAnonymous", SqlDbType.Bit, 0).Value = 0;
            }

            try
            {
                sqlConnection.Open();
                sqlCommand.ExecuteNonQuery();
            }
            catch (SqlException e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                sqlConnection.Close();
            }

            return Convert.ToInt32(sqlCommand.Parameters["deleted"].Value);
        }

        public override int DeleteProfiles(string[] userNames)
        {
            int deleted = 0;
            SqlConnection sqlConnection = new SqlConnection(connectionString);
            SqlCommand sqlCommand = new SqlCommand("Profiles_Del", sqlConnection);
            sqlCommand.CommandType = CommandType.StoredProcedure;
            sqlCommand.Connection = sqlConnection;
            //SqlTransaction transaction = null;


            try
            {
                sqlConnection.Open();
                //sqlCommand.Parameters.Add("userName", SqlDbType.NVarChar, 50);

                //transaction = sqlConnection.BeginTransaction();

                foreach (string userName in userNames)
                {
                    sqlCommand.Parameters.Add("@userName", SqlDbType.NVarChar, 50).Value = userName;
                    sqlCommand.ExecuteNonQuery();
                    deleted += 1;
                    sqlCommand.Parameters.Clear();
                }

                //transaction.Commit();

            }
            catch (SqlException e)
            {
                try
                {
                    //transaction.Rollback();
                }
                catch (Exception ex)
                {
                }
                throw new Exception(e.Message);
            }
            finally
            {
                sqlConnection.Close();
            }

            return deleted;
        }

        public override int DeleteProfiles(ProfileInfoCollection profiles)
        {
            string[] userNames = new string[profiles.Count];

            int index = 0;
            foreach (ProfileInfo profileInfo in profiles)
            {
                userNames[index] = profileInfo.UserName;
                index += 1;
            }

            return DeleteProfiles(userNames);
        }

        public override ProfileInfoCollection FindInactiveProfilesByUserName(ProfileAuthenticationOption authenticationOption, string userNameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
        {
            CheckParameters(pageIndex, pageSize);

            return GetProfileInfo(
            authenticationOption,
            userNameToMatch,
            userInactiveSinceDate,
            pageIndex,
            pageSize,
            out totalRecords
            );
        }

        public override ProfileInfoCollection FindProfilesByUserName(ProfileAuthenticationOption authenticationOption, string userNameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            CheckParameters(pageIndex, pageSize);

            return GetProfileInfo(
            authenticationOption,
            userNameToMatch,
            null,
            pageIndex,
            pageSize,
            out totalRecords
            );
        }

        public override ProfileInfoCollection GetAllInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
        {
            CheckParameters(pageIndex, pageSize);

            return GetProfileInfo(
            authenticationOption,
            null,
            userInactiveSinceDate,
            pageIndex,
            pageSize,
            out totalRecords
            );
        }

        public override ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords)
        {
            CheckParameters(pageIndex, pageSize);

            return GetProfileInfo(
            authenticationOption,
            null,
            null,
            pageIndex,
            pageSize,
            out totalRecords
            );
        }

        public override int GetNumberOfInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
        {
            int inactiveProfiles = 0;

            GetProfileInfo(authenticationOption, null, userInactiveSinceDate, 0, 0, out inactiveProfiles);

            return inactiveProfiles;
        }

        /// <summary>
        /// Get the property values for the user profile.
        /// </summary>
        /// <param name="context">Application context.</param>
        /// <param name="settingsProperties">Profile property settings.</param>
        /// <returns>Property setting values.</returns>
        public override System.Configuration.SettingsPropertyValueCollection GetPropertyValues(System.Configuration.SettingsContext context, System.Configuration.SettingsPropertyCollection settingsProperties)
        {
            string userName = context["UserName"].ToString();
            bool isAuthenticated = Convert.ToBoolean(context["IsAuthenticated"]);

            SqlConnection sqlConnection = new SqlConnection(connectionString);
            SqlCommand sqlCommand = new SqlCommand("Hr_Profiles", sqlConnection);
            sqlCommand.CommandType = CommandType.StoredProcedure;
            SqlDataReader sqlDataReader = null;

            sqlCommand.Parameters.Add("userName", SqlDbType.NVarChar, 50).Value = userName;
            
            SettingsPropertyValueCollection settingsValues = new SettingsPropertyValueCollection();

            try
            {
                sqlConnection.Open();
                sqlDataReader = sqlCommand.ExecuteReader(CommandBehavior.CloseConnection & CommandBehavior.SingleRow);

                sqlDataReader.Read();

                foreach (SettingsProperty property in settingsProperties)
                {
                    SettingsPropertyValue settingsPropertyValue = new SettingsPropertyValue(property);

                    if (sqlDataReader.HasRows)
                    {
                        switch (property.Name)
                        {
                            case "EmployeeId":
                                settingsPropertyValue.PropertyValue = sqlDataReader["EmployeeId"];
                                break;
                            case "EmployeeCode":
                                settingsPropertyValue.PropertyValue = sqlDataReader["EmployeeCode"];
                                break;
                            case "WindowsUser":
                                settingsPropertyValue.PropertyValue = sqlDataReader["WindowsUser"];
                                break;
                            case "AgentNumber":
                                settingsPropertyValue.PropertyValue = sqlDataReader["AgentNumber"];
                                break;
                            case "FullName":
                                settingsPropertyValue.PropertyValue = sqlDataReader["FullName"];
                                break;
                            case "BranchId":
                                settingsPropertyValue.PropertyValue = sqlDataReader["BranchId"];
                                break;
                            case "BranhCode":
                                settingsPropertyValue.PropertyValue = sqlDataReader["BranhCode"];
                                break;
                            case "BranhName":
                                settingsPropertyValue.PropertyValue = sqlDataReader["BranhName"];
                                break;
                            case "JobId":
                                settingsPropertyValue.PropertyValue = sqlDataReader["JobId"];
                                break;
                            case "JobCode":
                                settingsPropertyValue.PropertyValue = sqlDataReader["JobCode"];
                                break;
                            case "JobName":
                                settingsPropertyValue.PropertyValue = sqlDataReader["JobName"];
                                break;
                            case "Priority":
                                settingsPropertyValue.PropertyValue = sqlDataReader["Priority"];
                                break;
                            case "DepartId":
                                settingsPropertyValue.PropertyValue = sqlDataReader["DepartId"];
                                break;
                            case "DepartCode":
                                settingsPropertyValue.PropertyValue = sqlDataReader["DepartCode"];
                                break;
                            case "DepartName":
                                settingsPropertyValue.PropertyValue = sqlDataReader["DepartName"];
                                break;
                            case "AccountId":
                                settingsPropertyValue.PropertyValue = sqlDataReader["AccountId"];
                                break;
                            case "AccountName":
                                settingsPropertyValue.PropertyValue = sqlDataReader["AccountName"];
                                break;
                            default:
                                break;
                        }
                    }

                    settingsValues.Add(settingsPropertyValue);
                }
            }
            catch (SqlException e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                if (sqlDataReader != null)
                {
                    sqlDataReader.Close();
                }
            }

            return settingsValues;
        }

        public override void SetPropertyValues(System.Configuration.SettingsContext context, System.Configuration.SettingsPropertyValueCollection settingsPropertyValues)
        {
            string userName = context["UserName"].ToString();
            bool isAuthenticated = Convert.ToBoolean(context["IsAuthenticated"]);

            SqlConnection sqlConnection = new SqlConnection(connectionString);
            SqlCommand sqlCommand = new SqlCommand("ProfileData_Upd", sqlConnection);
            sqlCommand.CommandType = CommandType.StoredProcedure;

            sqlCommand.Parameters.Add("userName", SqlDbType.NVarChar, 50).Value = userName;
            sqlCommand.Parameters.Add("applicationName", SqlDbType.NVarChar, 50).Value = applicationName;
            sqlCommand.Parameters.Add("isAnonymous", SqlDbType.Bit, 0).Value = !isAuthenticated;

            foreach (SettingsPropertyValue settingsPropertyValue in settingsPropertyValues)
            {
                switch (settingsPropertyValue.Property.Name)
                {
                    case "FullName":
                        //sqlCommand.Parameters.Add("FullName", SqlDbType.NVarChar, 200).Value = settingsPropertyValue.PropertyValue.ToString();
                        break;
                    case "Mobile":
                        //sqlCommand.Parameters.Add("Mobile", SqlDbType.VarChar, 50).Value = settingsPropertyValue.PropertyValue.ToString();
                        break;
                    case "Phone":
                        //sqlCommand.Parameters.Add("Phone", SqlDbType.VarChar, 50).Value = settingsPropertyValue.PropertyValue.ToString();
                        break;
                    case "Email":
                        //sqlCommand.Parameters.Add("Email", SqlDbType.VarChar, 50).Value = settingsPropertyValue.PropertyValue.ToString();
                        break;
                    case "Address":
                        //sqlCommand.Parameters.Add("Address", SqlDbType.NVarChar, 200).Value = settingsPropertyValue.PropertyValue.ToString();
                        break;
                    default:
                        break;
                }
            }

            try
            {
                sqlConnection.Open();
                sqlCommand.ExecuteNonQuery();
            }
            catch (SqlException e)
            {
                //throw new Exception(e.Message);
            }
            finally
            {
                sqlConnection.Close();
            }
        }
        #endregion

        #region "Method"
        /// <summary>
        /// Verifies input parameters for page size and page index. 
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <remarks></remarks>
        private void CheckParameters(int pageIndex, int pageSize)
        {
            if (pageIndex < 0)
            {
                throw new ArgumentException("Page index must 0 or greater.");
            }
            if (pageSize < 1)
            {
                throw new ArgumentException("Page size must be greater than 0.");
            }
        }

        /// <summary>
        /// Get a collection of profiles based upon a user name matching string and inactivity date.
        /// </summary>
        /// <param name="authenticationOption">Current authentication option setting.</param>
        /// <param name="userNameToMatch">Characters representing user name to match (L to R).</param>
        /// <param name="userInactiveSinceDate">Inactivity date for deletion.</param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalRecords">Total records found (output).</param>
        /// <returns>Collection of profiles.</returns>
        private ProfileInfoCollection GetProfileInfo(
         ProfileAuthenticationOption authenticationOption,
         string usernameToMatch,
        object userInactiveSinceDate,
         int pageIndex,
         int pageSize,
        out int totalRecords
        )
        {

            SqlConnection sqlConnection = new SqlConnection(connectionString);
            SqlCommand sqlCommand = new SqlCommand("Profiles_Sel", sqlConnection);
            sqlCommand.CommandType = CommandType.StoredProcedure;
            sqlCommand.Connection = sqlConnection;
            SqlTransaction transaction = null;

            // if searching for a user name to match add the command text and parameters.
            if (String.IsNullOrEmpty(usernameToMatch))
            {
                sqlCommand.Parameters.Add("userName", SqlDbType.DateTime, 0).Value = usernameToMatch;
            }

            //if searching for inactive profiles add the command text and parameters.
            if (userInactiveSinceDate != null)
            {
                sqlCommand.Parameters.Add("inactivityDate", SqlDbType.DateTime, 0).Value = Convert.ToDateTime(userInactiveSinceDate);
            }

            // If searching for a anonymous or authenticated profiles, add the command text 
            // and parameters.
            if (authenticationOption == ProfileAuthenticationOption.Anonymous)
            {
                sqlCommand.Parameters.Add("isAnonymous", SqlDbType.Bit, 0).Value = 1;
            }
            else
            {
                sqlCommand.Parameters.Add("isAnonymous", SqlDbType.Bit, 0).Value = 0;
            }

            SqlDataReader sqlDataReader = null;
            ProfileInfoCollection profiles = new ProfileInfoCollection();

            // Count profiles only.
            if (pageSize == 0)
            {
                totalRecords = 0;
                return profiles;
            }

            int counter = 0;
            try
            {
                sqlConnection.Open();
                sqlDataReader = sqlCommand.ExecuteReader(CommandBehavior.CloseConnection);

                int startIndex = pageSize * (pageIndex - 1);
                int endIndex = startIndex + pageSize - 1;

                while (sqlDataReader.Read())
                {
                    if (counter >= startIndex)
                    {
                        ProfileInfo profileInfo = new ProfileInfo(
                       (sqlDataReader["UserName"].ToString()),
                       Convert.ToBoolean(sqlDataReader["IsAnonymous"]),
                       Convert.ToDateTime(sqlDataReader["LastActivity"]),
                       Convert.ToDateTime(sqlDataReader["LastUpdated"]),
                       0
                       );

                        profiles.Add(profileInfo);
                    }

                    if (counter >= endIndex)
                    {
                        sqlCommand.Cancel();
                    }

                    counter += 1;
                }
            }
            catch (SqlException e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                sqlConnection.Close();
            }

            totalRecords = counter;

            return profiles;

        }

        /// <summary>
        /// Lay thong tin profile cua user
        /// </summary>
        /// <param name="username">user name login</param>
        /// <returns></returns>
        public SettingsPropertyValueCollection GetProfileData(string userName)
        {
            ProfileProvider provider = ProfileManager.Providers["MPProfileProvider"];
            applicationName = provider.ApplicationName;
            connectionString = MP.Core.Library.SqlHelper.ConnectionStringOBS;

            SqlConnection sqlConnection = new SqlConnection(connectionString);
            SqlCommand sqlCommand = new SqlCommand("Hr_Profiles", sqlConnection);
            sqlCommand.CommandType = CommandType.StoredProcedure;
            SqlDataReader sqlDataReader = null;

            sqlCommand.Parameters.Add("userName", SqlDbType.NVarChar, 50).Value = userName;

            SettingsPropertyValueCollection settingsValues = new SettingsPropertyValueCollection();
            SettingsPropertyCollection settingsProperties = ProfileBase.Properties;
            try
            {
                sqlConnection.Open();
                sqlDataReader = sqlCommand.ExecuteReader(CommandBehavior.CloseConnection & CommandBehavior.SingleRow);

                sqlDataReader.Read();

                foreach (SettingsProperty property in settingsProperties)
                {
                    SettingsPropertyValue settingsPropertyValue = new SettingsPropertyValue(property);

                    if (sqlDataReader.HasRows)
                    {
                        switch (property.Name)
                        {
                            case "EmployeeId":
                                settingsPropertyValue.PropertyValue = sqlDataReader["EmployeeId"];
                                break;
                            case "EmployeeCode":
                                settingsPropertyValue.PropertyValue = sqlDataReader["EmployeeCode"];
                                break;
                            case "WindowsUser":
                                settingsPropertyValue.PropertyValue = sqlDataReader["WindowsUser"];
                                break;
                            case "AgentNumber":
                                settingsPropertyValue.PropertyValue = sqlDataReader["AgentNumber"];
                                break;
                            case "FullName":
                                settingsPropertyValue.PropertyValue = sqlDataReader["FullName"];
                                break;
                            case "BranchId":
                                settingsPropertyValue.PropertyValue = sqlDataReader["BranchId"];
                                break;
                            case "BranhCode":
                                settingsPropertyValue.PropertyValue = sqlDataReader["BranhCode"];
                                break;
                            case "BranhName":
                                settingsPropertyValue.PropertyValue = sqlDataReader["BranhName"];
                                break;
                            case "JobId":
                                settingsPropertyValue.PropertyValue = sqlDataReader["JobId"];
                                break;
                            case "JobCode":
                                settingsPropertyValue.PropertyValue = sqlDataReader["JobCode"];
                                break;
                            case "JobName":
                                settingsPropertyValue.PropertyValue = sqlDataReader["JobName"];
                                break;
                            case "Priority":
                                settingsPropertyValue.PropertyValue = sqlDataReader["Priority"];
                                break;
                            case "DepartId":
                                settingsPropertyValue.PropertyValue = sqlDataReader["DepartId"];
                                break;
                            case "DepartCode":
                                settingsPropertyValue.PropertyValue = sqlDataReader["DepartCode"];
                                break;
                            case "DepartName":
                                settingsPropertyValue.PropertyValue = sqlDataReader["DepartName"];
                                break;
                            case "AccountId":
                                settingsPropertyValue.PropertyValue = sqlDataReader["AccountId"];
                                break;
                            case "AccountName":
                                settingsPropertyValue.PropertyValue = sqlDataReader["AccountName"];
                                break;
                            default:
                                break;
                        }
                    }

                    settingsValues.Add(settingsPropertyValue);
                }
            }
            catch (SqlException e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                if (sqlDataReader != null)
                {
                    sqlDataReader.Close();
                }
            }

            return settingsValues;
        }

        public void UpdateProfileData(SettingsPropertyValueCollection data, string userName)
        {
            ProfileProvider provider = ProfileManager.Providers["MPProfileProvider"];
            applicationName = provider.ApplicationName;
            connectionString = MP.Core.Library.SqlHelper.ConnectionStringOBS;

            SqlConnection sqlConnection = new SqlConnection(connectionString);
            SqlCommand sqlCommand = new SqlCommand("ProfileData_Upd2", sqlConnection);
            sqlCommand.CommandType = CommandType.StoredProcedure;
            SqlDataReader sqlDataReader = null;

            sqlCommand.Parameters.Add("userName", SqlDbType.NVarChar, 50).Value = userName;
            sqlCommand.Parameters.Add("applicationName", SqlDbType.NVarChar, 50).Value = applicationName;
            sqlCommand.Parameters.Add("FullName", SqlDbType.NVarChar, 200).Value = data["FullName"].PropertyValue;
            sqlCommand.Parameters.Add("Mobile", SqlDbType.VarChar, 50).Value = data["Mobile"].PropertyValue;
            sqlCommand.Parameters.Add("Phone", SqlDbType.VarChar, 50).Value = data["Phone"].PropertyValue;
            sqlCommand.Parameters.Add("Email", SqlDbType.VarChar, 50).Value = data["Email"].PropertyValue;
            sqlCommand.Parameters.Add("Address", SqlDbType.NVarChar, 200).Value = data["Address"].PropertyValue;
            
            try
            {
                sqlConnection.Open();
                sqlCommand.ExecuteNonQuery();
            }
            catch (SqlException e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                if (sqlDataReader != null)
                {
                    sqlDataReader.Close();
                }
            }
        }

        #endregion
    }
}
